#include "depui/depui.h"
#include <string.h>

#define MXMODULE_EDITTEXT
#define MXMODULE_FILESEL

#define MX__TEXTEDITOR_OPENID 1
#define MX__TEXTEDITOR_SAVEID 2

void mx_texteditor_save(const MX_TEXTEDITOR * app, const char *path)
{
	int len = 0;
	const char *text = mx_text(&app->edit, &len);

	FILE *stream = fopen(path, "wb");

	if (stream) {
		int i = 0;

		if (len == -1)
			len = 0x7fff;

		while ((text) && (text[i]) && (i < len))
			fputc(text[i++], stream);

		fclose(stream);
	}
}

void mx_texteditor_open(MX_TEXTEDITOR * app, const char *path)
{
	FILE *stream = fopen(path, "r");

	if (stream) {
		int c;
		MX_VECTOR(char) temp;

		mx_vector(&temp);
		mx_vector_reserve(&temp, 0xfff);

		while ((c = fgetc(stream)) != EOF) {
			const char bytetemp = c;

			mx_vector_append(&temp, &bytetemp, 1);
		}

		mx_text_set(&app->edit, temp.data, (int) mx_vector_size(&temp), free);
		fclose(stream);
	}
}

void mx_texteditor_handler(MX_WIN * win)
{
	MX_TEXTEDITOR *app = (MX_TEXTEDITOR *) win;

	/* Pick some default size */
	if (mx_eventmatch(MX_DEFAULTRECT, win)) {
		MX_RECT *rrect = mx_defaultrect_data();

		rrect->x2 = rrect->x1 + 280;
		rrect->y2 = rrect->y1 + 160;
		return;

		/* Place the objects in a nice place when geometry is set */
	} else if ((mx_eventmatch(MX_GEOMETRY, win))
			   || (mx_eventmatch(MX_THEME_CHANGE, win))) {
		mx_defaultrect(&app->open, 0);
		mx_move(&app->open, 1, 1);
		mx_geometry(&app->open);

		mx_defaultrect(&app->save, 0);
		mx_layout(&app->save, MX_LAYOUT_Y1 | MX_LAYOUT_RIGHT, &app->open, 2, 0);
		mx_geometry(&app->save);

		mx_defaultrect(&app->edit, 0);
		mx_geometry(&app->edit);

		mx_layout(&app->scroll, MX_LAYOUT_X1 | MX_LAYOUT_BOTTOM, &app->open, 0, 2);
		mx_resize(&app->scroll, mx_w(win) - 2, mx_h(win) - mx_h(&app->open) - 3);
		mx_geometry(&app->scroll);

	} else if (mx_eventmatch(MX_KEY, &app->edit)) {
		const MX_KEY_INFO *info = mx_key_info();

		sprintf(app->message, "ascii %i code %i", (int) info->ascii, (int) info->code);
		mx_text_set(app, app->message, -1, 0);
		mx_win_dirty(app);

		mx_default_handler();

		mx_geometry(&app->scroll);
		mx_defaultrect(&app->edit, 0);
		mx_edittext_cursorscroll(&app->edit);

		return;

	} else if (mx_eventmatch(MX_SELECT, &app->open)) {
		MX_FILESEL *sel = mx_fileselwin(0, 0, 0, MX__TEXTEDITOR_OPENID);

		mx_text_set(sel, "open", -1, 0);
		mx_filesel_refresh(sel);
		mx_defaultrect(sel, 0);
		mx_layout(sel, MX_LAYOUT_CENTER, (MX_OBJ *) 0, 0, 0);
		mx_geometry(sel);

		mx_win_dirty(sel);
		return;

	} else if (mx_eventmatch(MX_SELECT, &app->save)) {
		MX_FILESEL *sel = mx_fileselwin(0, 0, 0, MX__TEXTEDITOR_SAVEID);

		mx_text_set(sel, "Save", -1, 0);
		mx_filesel_existing(sel, false);
		mx_filesel_refresh(sel);
		mx_defaultrect(sel, 0);
		mx_layout(sel, MX_LAYOUT_CENTER, (MX_OBJ *) 0, 0, 0);
		mx_geometry(sel);

		mx_win_dirty(sel);
		return;
	}

	if (mx.event == MX_FILESEL_OK) {
		const char *path = mx_filesel_info(MX__TEXTEDITOR_OPENID);

		if (path) {
			mx_texteditor_open(app, path);
			mx_defaultrect(&app->edit, 0);
			mx_edittext_cursorpos(&app->edit, 0);

			mx_scroll_reset(&app->scroll);
			mx_geometry(&app->scroll);
		}

		path = mx_filesel_info(MX__TEXTEDITOR_SAVEID);

		if (path)
			mx_texteditor_save(app, path);

		mx_win_dirty(win);
	}

	mx_default_handler();
}

MX_TEXTEDITOR *mx_texteditorwin(MX_TEXTEDITOR * app, size_t size, MX_HANDLER handler, int theid)
{
	MXMINSIZE(size, MX_TEXTEDITOR);

	if (!handler)
		handler = mx_texteditor_handler;

	app = (MX_TEXTEDITOR *) mx_win(app, size, handler, theid);

	if (app) {
		mx_button(&app->open, 0, app, 0);
		mx_text_set(&app->open, "Open", -1, 0);

		mx_button(&app->save, 0, app, 0);
		mx_text_set(&app->save, "Save", -1, 0);

		mx_scroll(&app->scroll, 0, app, 0);
		strcpy(app->message, "...");
		mx_text_set(app, app->message, -1, 0);

		mx_edittext(&app->edit, 0, &app->scroll, 0);
		mx_text_set(&app->edit, "", -1, 0);
		mx_focus_default(&app->edit);

		mx_scroll_reset(&app->scroll);
	}
	return app;
}
